home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / modula2 / lpr / realinou.mod < prev    next >
Encoding:
Modula Implementation  |  1994-09-22  |  23.7 KB  |  864 lines

  1. IMPLEMENTATION MODULE RealInOut;
  2.  
  3. FROM InOut    IMPORT Write, ReadString, WriteString;
  4. FROM SYSTEM   IMPORT ADR, LONG;
  5. FROM System   IMPORT FLOATd, TRUNCd;
  6. IMPORT InOut;
  7.  
  8.   CONST LenText = 80;
  9.   TYPE  String  = ARRAY [0..LenText] OF CHAR;
  10.   
  11.     CONST MaxDigits = 8;
  12.     VAR   neg : BOOLEAN;
  13.           a   : REAL;
  14.           i   : INTEGER;
  15.           MINREAL : REAL;
  16.           nul : INTEGER; (* ORD('0') *)
  17.  
  18.     PROCEDURE atoi(a : REAL; i : INTEGER; VAR OK : BOOLEAN) : REAL;
  19.       VAR b   : REAL;
  20.           k,m : CARDINAL;
  21.           ib : RECORD
  22.                  CASE : BOOLEAN OF
  23.                    TRUE : i : INTEGER |
  24.                    FALSE: b : BITSET
  25.                  END
  26.                END;
  27.       BEGIN
  28.         b:=1.0;
  29.         IF i<0 THEN 
  30.           i:=-i;
  31.           a:=1.0/a
  32.         ELSIF i=0 THEN
  33.           OK:=TRUE;
  34.           RETURN b
  35.         END;
  36.         m:=15;
  37.         ib.i:=i;
  38.         WHILE ~(m IN ib.b) DO DEC(m) END;
  39.         FOR k:=0 TO m DO
  40.           IF k IN ib.b THEN b:=b*a END;
  41.           IF k<m THEN
  42.             IF ABS(a)>1.0 THEN 
  43.               OK:=(ABS(b)<(MAX(REAL)/a)/a) & (ABS(a)<MAX(REAL)/ABS(a))
  44.             ELSIF ABS(a)<1.0 THEN
  45.               OK:=(ABS(b)>(MINREAL/a)/a) & (ABS(a)>MINREAL/ABS(a))
  46.             ELSE
  47.               OK:=TRUE
  48.             END; 
  49.             IF OK THEN a:=a*a ELSE RETURN 0.0 END
  50.           END
  51.         END;
  52.         RETURN b
  53.       END atoi;
  54.       
  55.     PROCEDURE StringToReal
  56.               (VAR s : ARRAY OF CHAR; VAR val : REAL; VAR ReadOK : BOOLEAN);
  57.       VAR nege   : BOOLEAN;
  58.           pos    : INTEGER;
  59.           i,temp : INTEGER;
  60.           tch    : CHAR;    
  61.           rval, sval, fct  : REAL;
  62.       PROCEDURE ReadCH(VAR ch : CHAR);
  63.         BEGIN
  64.           ReadOK:=pos<HIGH(s);
  65.           IF ReadOK THEN 
  66.             ch:=s[pos];
  67.             INC(pos)
  68.           ELSE
  69.             ch:=' '
  70.           END
  71.         END ReadCH;
  72.     BEGIN
  73.       pos:=0;
  74.       ReadCH(tch);
  75.       IF ~ReadOK THEN RETURN END; 
  76.       WHILE tch=' ' DO 
  77.         ReadCH(tch);
  78.         IF ~ReadOK THEN RETURN END 
  79.       END;
  80.       neg:=tch='-';
  81.       IF neg OR (tch='+') THEN 
  82.         ReadCH(tch); 
  83.         IF ~ReadOK THEN RETURN END 
  84.       END;
  85.       sval:=0.0;
  86.       ReadOK:=FALSE;
  87.       WHILE (tch>='0') AND (tch<='9') DO 
  88.         sval:=10.0*sval+FLOAT(ORD(tch)-ORD('0'));
  89.         ReadCH(tch);
  90.         IF ~ReadOK THEN RETURN END 
  91.       END;
  92.       IF tch='.' THEN 
  93.         ReadCH(tch);
  94.         IF ~ReadOK THEN RETURN END; 
  95.         rval:=1.0;
  96.         WHILE (tch>='0') AND (tch<='9') DO 
  97.           sval:=10.0*sval+FLOAT(ORD(tch)-ORD('0'));
  98.           rval:=10.0*rval;
  99.           ReadCH(tch);
  100.           IF ~ReadOK THEN RETURN END 
  101.         END;
  102.         sval:=sval/rval
  103.       END;
  104.       IF tch='E' THEN
  105.         ReadCH(tch);
  106.         IF ~ReadOK THEN RETURN END; 
  107.         nege:=tch='-';
  108.         IF nege OR (tch='+') THEN 
  109.           ReadCH(tch); 
  110.           IF ~ReadOK THEN RETURN END 
  111.         END;
  112.         i:=0;
  113.         LOOP
  114.           IF (tch<'0') OR (tch>'9') THEN EXIT END;
  115.           temp:=ORD(tch)-ORD('0');
  116.           i:=10*i+temp;
  117.           ReadCH(tch);
  118.           IF ~ReadOK THEN RETURN END 
  119.         END;
  120.         fct:=atoi(10.0,i,ReadOK);
  121.         IF ~ReadOK THEN RETURN END; 
  122.         IF nege THEN 
  123.           ReadOK:=sval>MINREAL*fct;
  124.           IF ~ReadOK THEN RETURN END; 
  125.           sval:=sval/fct
  126.         ELSE
  127.           ReadOK:=sval<MAX(REAL)/fct; 
  128.           IF ~ReadOK THEN RETURN END; 
  129.           sval:=sval*fct
  130.         END
  131.       END;            
  132.       IF ~ReadOK THEN RETURN END; 
  133.       IF neg THEN sval:=-sval END;
  134.       val:=sval;
  135.       ReadOK:=tch<=' '
  136.     END StringToReal;
  137.     
  138.     PROCEDURE ReadReal(VAR a : REAL);
  139.       VAR s : String;
  140.       BEGIN
  141.         ReadString(s);
  142.         Done:=InOut.Done;
  143.         IF Done THEN StringToReal(s,a,Done) END
  144.       END ReadReal;
  145.     
  146.     PROCEDURE PreScale;
  147.     (*        Convert the number to be in the range 1 to 10 (unless zero)
  148.               i returns places shifted in process *)
  149.       BEGIN
  150.         neg:=a<0.0;
  151.         IF neg THEN a:=-a END;
  152.         (* calculate whole digits size *)
  153.         i:=0;
  154.         IF a<>0.0 THEN
  155.           WHILE a>=1.0E7 DO 
  156.             a:=a/1.0E7;
  157.             INC(i,7)
  158.           END;
  159.           WHILE a>=10.0 DO
  160.             a:=a/10.0;
  161.             INC(i)
  162.           END;
  163.           WHILE a<1.0E-7 DO
  164.             a:=1.0E7*a;
  165.             DEC(i,7);
  166.             IF i<-38 THEN 
  167.               i:=0;
  168.               a:=0.0;
  169.               RETURN
  170.             END
  171.           END;
  172.           WHILE a<1.0 DO
  173.             a:=10.0*a;
  174.             DEC(i);
  175.             IF i<-38 THEN 
  176.               i:=0;
  177.               a:=0.0;
  178.               RETURN
  179.             END
  180.           END
  181.         END
  182.       END PreScale;
  183.   
  184.     PROCEDURE RealToString
  185.                  (VAR Text : ARRAY OF CHAR; c : REAL; size : INTEGER);
  186.       (* output a real number *)
  187.       VAR sigdigits       : INTEGER;
  188.           placesbeforedot : INTEGER;
  189.           pos             : INTEGER;
  190.           j,k,l           : INTEGER;
  191.           chs             : ARRAY [1..15] OF CHAR;
  192.           dummy           : BOOLEAN;
  193.       PROCEDURE WriteCH(ch : CHAR);
  194.         BEGIN
  195.           IF pos<HIGH(Text) THEN
  196.             Text[pos]:=ch;
  197.             INC(pos)
  198.           END
  199.         END WriteCH;
  200.       BEGIN
  201.         IF size>=HIGH(Text) THEN size:=HIGH(Text)-1 END;
  202.         pos:=0;
  203.         a:=c;
  204.         PreScale;
  205.         placesbeforedot:=1;
  206.   
  207.         (*      Convert to engineering form if required.
  208.                 This code does so by shifting more digits in front of
  209.                 the dot.
  210.                 If you want to shift the other way, change the signs
  211.                 on the numbers. *)
  212.    
  213.         IF Engineering THEN
  214.           WHILE (i MOD 3)<>0 DO 
  215.             DEC(i);
  216.             INC(placesbeforedot);
  217.           END
  218.         END;
  219.  
  220.         (*      placesbeforedot now contains the number of places to 
  221.                 precede the decimal point *)
  222.  
  223.         sigdigits:=size-6;
  224.         IF sigdigits>SigDigits THEN sigdigits:=SigDigits END;
  225.         IF sigdigits<2 THEN sigdigits:=2 END;
  226.         IF sigdigits>MaxDigits THEN sigdigits:=MaxDigits END;
  227.         IF Engineering & (sigdigits<3) THEN sigdigits:=3 END;
  228.         IF size>sigdigits+6 THEN
  229.           FOR l:=size-(sigdigits+6) TO 1 BY -1 DO WriteCH(' ') END
  230.         END;
  231.         IF neg THEN 
  232.           WriteCH('-')
  233.         ELSE 
  234.           WriteCH(' ')  
  235.         END;
  236.  
  237.         (*      write out the number *)
  238.        
  239.         a:=a+atoi(0.1,sigdigits,dummy)*5.0;
  240.         IF TRUNC(a)>9 THEN
  241.           a:=a/10.0;
  242.           INC(i)
  243.         END;
  244.         FOR l:=1 TO sigdigits DO
  245.            k:=TRUNC(a);
  246.            IF k>9 THEN 
  247.              k:=9;
  248.              a:=10.0
  249.            END;
  250.            WriteCH(CHR(k+ORD('0')));
  251.            a:=10.0*(a-FLOAT(k));
  252.            IF a<0.0 THEN a:=0.0 END;
  253.            IF l=placesbeforedot THEN WriteCH('.') END
  254.          END;
  255.          IF (i<>0) OR ForceExponent THEN
  256.            WriteCH('E');
  257.            IF i<0 THEN
  258.              WriteCH('-');
  259.              i:=-i
  260.            ELSE 
  261.              WriteCH('+');
  262.            END;
  263.            FOR k:=1 TO 2 DO
  264.              j:=i DIV 10;
  265.              l:=i-10*j;
  266.              chs[k]:=CHR(l+ORD('0'));
  267.              i:=j
  268.            END;
  269.            FOR k:=2 TO 1 BY -1 DO  WriteCH(chs[k]) END
  270.          END;
  271.          Text[pos]:=0C
  272.        END RealToString;
  273.      
  274.     PROCEDURE WriteReal(c : REAL; size : INTEGER);
  275.       VAR s : String;
  276.       BEGIN
  277.         RealToString(s,c,size);
  278.         WriteString(s)
  279.       END WriteReal;
  280.   
  281.     PROCEDURE RealToStringFixed
  282.               (VAR Text : ARRAY OF CHAR; x : REAL; size, places : INTEGER);
  283.       (*  output a real number *)
  284.       VAR  placesbeforedot  : INTEGER;
  285.            wholeplaces      : INTEGER;
  286.            pos, k, l        : INTEGER;
  287.            digitnumber      : INTEGER;
  288.            storeSigDigits   : INTEGER;
  289.            storeEngineering : BOOLEAN;
  290.            dummy            : BOOLEAN;
  291.       PROCEDURE WriteCH(ch : CHAR);
  292.         BEGIN
  293.           IF pos<HIGH(Text) THEN
  294.             Text[pos]:=ch;
  295.             INC(pos)
  296.           END
  297.         END WriteCH;
  298.       BEGIN
  299.         IF size>=HIGH(Text) THEN size:=HIGH(Text)-1 END;
  300.         pos:=0;
  301.         a:=x;
  302.         PreScale;
  303.         IF places>7 THEN places:=7 END;
  304.         IF size=0 THEN size:=1 END;
  305.         IF (size=1) & neg THEN size:=2 END;
  306.         IF places>size-1 THEN places:=size-1 END;
  307.         placesbeforedot:=size-places-1;
  308.         IF neg & (placesbeforedot>0)THEN DEC(placesbeforedot) END;
  309.         IF i<=0 THEN    
  310.           wholeplaces:=1;
  311.           a:=ABS(x);
  312.           i:=0
  313.         ELSE            
  314.           wholeplaces:=i+1 
  315.         END;
  316.         IF wholeplaces>placesbeforedot THEN 
  317.           storeSigDigits:=SigDigits;
  318.           storeEngineering:=Engineering;
  319.           SigDigits:=places+1;
  320.           Engineering:=FALSE;
  321.           RealToString(Text,x,size);
  322.           SigDigits:=storeSigDigits;
  323.           Engineering:=storeEngineering;
  324.           RETURN
  325.         END;
  326.         a:=a+atoi(0.1,wholeplaces+places,dummy)*5.0;
  327.         FOR l:=placesbeforedot TO wholeplaces+1 BY -1 DO WriteCH(' ') END;
  328.         IF neg THEN WriteCH('-') END;
  329.         digitnumber:=1;
  330.         FOR l:=wholeplaces TO 1 BY -1 DO
  331.           k:=TRUNC(a);
  332.           IF k>9 THEN k:=9 END;
  333.           IF digitnumber<=MaxDigits THEN
  334.             WriteCH(CHR(k+ORD('0')))
  335.           ELSE
  336.             WriteCH('0')
  337.           END;
  338.           INC(digitnumber);
  339.           a:=10.0*(a-FLOAT(k));
  340.           IF a<0.0 THEN a:=0.0 END
  341.         END;
  342.         IF digitnumber<=MaxDigits THEN WriteCH('.') ELSE WriteCH(' ') END;
  343.         FOR l:=1 TO places DO
  344.           k:=TRUNC(a);
  345.           IF k>9 THEN k:=9; a:=10.0 END;
  346.           IF digitnumber<=MaxDigits THEN
  347.             WriteCH(CHR(k+ORD('0')))
  348.           ELSE 
  349.             WriteCH(' ')
  350.           END;
  351.           INC(digitnumber);
  352.           a:=10.0*(a-FLOAT(k));
  353.           IF a<0.0 THEN a:=0.0 END
  354.         END;
  355.         Text[pos]:=0C
  356.       END RealToStringFixed;
  357.     
  358.     PROCEDURE WriteRealFixed(x : REAL; size, places : INTEGER);
  359.       VAR s : String;
  360.       BEGIN
  361.         RealToStringFixed(s,x,size,places);
  362.         WriteString(s)
  363.       END WriteRealFixed;
  364.       
  365.         
  366.     CONST LMaxDigits = 16;
  367.     VAR   La      : LONGREAL;
  368.           MinLong : LONGREAL;
  369.           One,Five,Ten,Tenth,Zero,E14,EM4,EM8,EM12,EM14,EM16,EM20, 
  370.           TwoEM16  : LONGREAL;
  371.         
  372.     PROCEDURE Rec(x : LONGREAL) : LONGREAL;
  373.       VAR y,d : LONGREAL;
  374.       BEGIN
  375.         y:=One/x;
  376.         REPEAT 
  377.           d:=x*y-One;
  378.           y:=y*(One-d);
  379.         UNTIL ABS(d)<TwoEM16;
  380.         RETURN y
  381.       END Rec;
  382.         
  383.   PROCEDURE Long(a,b,c,d,e,f : INTEGER) : LONGREAL;
  384.     VAR Sum : LONGREAL;
  385.         n   : INTEGER;
  386.     BEGIN
  387.       INC(f); 
  388.       Sum:=FLOATd(a)*EM4+FLOATd(b)*EM8+FLOATd(c)*EM12+
  389.            FLOATd(d)*EM16+FLOATd(e)*EM20;
  390.       IF f=0 THEN RETURN Sum END;
  391.       IF f>0 THEN
  392.         FOR n:=1 TO f DO Sum:=Sum*Ten END  
  393.       ELSE
  394.         FOR n:=1 TO -f DO Sum:=Sum*Tenth END
  395.       END;
  396.       RETURN Sum
  397.     END Long;
  398.   
  399.     PROCEDURE Latoi
  400.                 (La : LONGREAL; i : INTEGER; VAR OK : BOOLEAN) : LONGREAL;
  401.       VAR b,r : LONGREAL;
  402.           k,m : CARDINAL;
  403.           ib : RECORD
  404.                  CASE : BOOLEAN OF
  405.                    TRUE : i : INTEGER |
  406.                    FALSE: b : BITSET
  407.                  END
  408.                END;
  409.       BEGIN
  410.         b:=1.0;
  411.         IF i<0 THEN 
  412.           i:=-i;
  413.           La:=Rec(La)
  414.         ELSIF i=0 THEN
  415.           OK:=TRUE;
  416.           RETURN b
  417.         END;
  418.         m:=15;
  419.         ib.i:=i;
  420.         WHILE ~(m IN ib.b) DO DEC(m) END;
  421.         FOR k:=0 TO m DO
  422.           IF k IN ib.b THEN b:=b*La END;
  423.           IF k<m THEN
  424.             r:=Rec(La);
  425.             IF ABS(La)>One THEN 
  426.               OK:=(ABS(b)<(MAX(LONGREAL)*r)*r) & 
  427.                   (ABS(La)<MAX(LONGREAL)*ABS(r))
  428.             ELSIF ABS(La)<One THEN
  429.               OK:=(ABS(b)>(MinLong*r)*r) & 
  430.                   (ABS(La)>MinLong*ABS(r))
  431.             ELSE
  432.               OK:=TRUE
  433.             END; 
  434.             IF OK THEN La:=La*La ELSE RETURN Zero END
  435.           END
  436.         END;
  437.         RETURN b
  438.       END Latoi;
  439.       
  440.     PROCEDURE StringToLongReal
  441.           (VAR s : ARRAY OF CHAR; VAR val : LONGREAL; VAR ReadOK : BOOLEAN);
  442.       VAR nege : BOOLEAN;
  443.           pos  : INTEGER;
  444.           i    : INTEGER;
  445.           tch  : CHAR;    
  446.           rval, sval, fct  : LONGREAL;
  447.           temp : INTEGER;
  448.       PROCEDURE ReadCH(VAR ch : CHAR);
  449.         BEGIN
  450.           ReadOK:=pos<HIGH(s);
  451.           IF ReadOK THEN 
  452.             ch:=s[pos];
  453.             INC(pos)
  454.           ELSE
  455.             ch:=' '
  456.           END
  457.         END ReadCH;
  458.     BEGIN
  459.       pos:=0;
  460.       ReadCH(tch);
  461.       IF ~ReadOK THEN RETURN END; 
  462.       WHILE tch=' ' DO 
  463.         ReadCH(tch);
  464.         IF ~ReadOK THEN RETURN END 
  465.       END;
  466.       neg:=tch='-';
  467.       IF neg OR (tch='+') THEN 
  468.         ReadCH(tch); 
  469.         IF ~ReadOK THEN RETURN END 
  470.       END;
  471.       sval:=0.0;
  472.       ReadOK:=FALSE;
  473.       WHILE (tch>='0') AND (tch<='9') DO 
  474.         sval:=Ten*sval+FLOATd(ORD(tch)-ORD('0'));
  475.         ReadCH(tch);
  476.         IF ~ReadOK THEN RETURN END 
  477.       END;
  478.       IF tch='.' THEN 
  479.         ReadCH(tch);
  480.         IF ~ReadOK THEN RETURN END; 
  481.         rval:=1.0;
  482.         WHILE (tch>='0') AND (tch<='9') DO 
  483.           sval:=Ten*sval+FLOATd(ORD(tch)-ORD('0'));
  484.           rval:=Ten*rval;
  485.           ReadCH(tch);
  486.           IF ~ReadOK THEN RETURN END 
  487.        END;
  488.        sval:=sval*Rec(rval)
  489.       END;
  490.       IF tch='E' THEN
  491.         ReadCH(tch);
  492.         IF ~ReadOK THEN RETURN END; 
  493.         nege:=tch='-';
  494.         IF nege OR (tch='+') THEN 
  495.           ReadCH(tch); 
  496.           IF ~ReadOK THEN RETURN END 
  497.         END;
  498.         i:=0;
  499.         LOOP
  500.           IF (tch<'0') OR (tch>'9') THEN EXIT END;
  501.           temp:=ORD(tch)-ORD('0');
  502.           i:=10*i+temp;
  503.           ReadCH(tch);
  504.           IF ~ReadOK THEN RETURN END 
  505.         END;
  506.         fct:=Latoi(Ten,i,ReadOK);
  507.         IF ~ReadOK THEN RETURN END; 
  508.         IF nege THEN 
  509.           ReadOK:=sval>MinLong*fct;
  510.           IF ~ReadOK THEN RETURN END; 
  511.           sval:=sval*Rec(fct)
  512.         ELSE
  513.           ReadOK:=sval<MAX(LONGREAL)*Rec(fct); 
  514.           IF ~ReadOK THEN RETURN END; 
  515.           sval:=sval*fct
  516.         END
  517.       END;            
  518.       IF ~ReadOK THEN RETURN END; 
  519.       IF neg THEN sval:=-sval END;
  520.       val:=sval;
  521.       ReadOK:=tch<=' '
  522.     END StringToLongReal;
  523.     
  524.     PROCEDURE ReadLongReal(VAR a : LONGREAL);
  525.       VAR s : String;
  526.       BEGIN
  527.         ReadString(s);
  528.         Done:=InOut.Done;
  529.         IF Done THEN StringToLongReal(s,a,Done) END
  530.       END ReadLongReal;
  531.     
  532.     PROCEDURE LPreScale;
  533.     (*        Convert the number to be in the range 1 to 10 (unless zero)
  534.               i returns places shifted in process *)
  535.       BEGIN
  536.         neg:=La<Zero;
  537.         IF neg THEN La:=-La END;
  538.         (* calculate whole digits size *)
  539.         i:=0;
  540.         IF La<>Zero THEN
  541.           WHILE La>=E14 DO 
  542.             La:=La*EM14;
  543.             INC(i,14)
  544.           END;
  545.           WHILE La>=Ten DO
  546.             La:=La*Tenth;
  547.             INC(i)
  548.           END;
  549.           WHILE La<EM14 DO
  550.             La:=E14*La;
  551.             DEC(i,14);
  552.             IF i<-308 THEN 
  553.               i:=0;
  554.               La:=0.0;
  555.               RETURN
  556.             END
  557.           END;
  558.           WHILE La<One DO
  559.             La:=Ten*La;
  560.             DEC(i);
  561.             IF i<-308 THEN 
  562.               i:=0;
  563.               La:=0.0;
  564.               RETURN
  565.             END
  566.           END
  567.         END
  568.       END LPreScale;
  569.   
  570.     PROCEDURE LongRealToString
  571.                (VAR Text : ARRAY OF CHAR; c : LONGREAL; size : INTEGER);
  572.       (* output a real number *)
  573.       VAR sigdigits       : INTEGER;
  574.           placesbeforedot : INTEGER;
  575.           pos             : INTEGER;
  576.           j               : INTEGER;
  577.           k,l             : INTEGER;
  578.           chs             : ARRAY [1..15] OF CHAR;
  579.           dummy           : BOOLEAN;
  580.       PROCEDURE WriteCH(ch : CHAR);
  581.         BEGIN
  582.           IF pos<HIGH(Text) THEN
  583.             Text[pos]:=ch;
  584.             INC(pos)
  585.           END
  586.         END WriteCH;
  587.       BEGIN
  588.         IF size>=HIGH(Text) THEN size:=HIGH(Text)-1 END;
  589.         pos:=0;
  590.         La:=c;
  591.         LPreScale;
  592.         placesbeforedot:=1;
  593.   
  594.         (*      Convert to engineering form if required.
  595.                 This code does so by shifting more digits in front of
  596.                 the dot.
  597.                 If you want to shift the other way, change the signs
  598.                 on the numbers. *)
  599.    
  600.         IF LongEngineering THEN
  601.           WHILE (i MOD 3)<>0 DO 
  602.             DEC(i);
  603.             INC(placesbeforedot);
  604.           END
  605.         END;
  606.  
  607.         (*      placesbeforedot now contains the number of places to 
  608.                 precede the decimal point *)
  609.  
  610.         sigdigits:=size-7;
  611.         IF sigdigits>LongSigDigits THEN sigdigits:=LongSigDigits END;
  612.         IF sigdigits<2 THEN sigdigits:=2 END;
  613.         IF sigdigits>LMaxDigits THEN sigdigits:=LMaxDigits END;
  614.         IF LongEngineering & (sigdigits<3) THEN sigdigits:=3 END;
  615.         IF size>sigdigits+7 THEN
  616.           FOR l:=size-(sigdigits+7) TO 1 BY -1 DO WriteCH(' ') END
  617.         END;
  618.         IF neg THEN 
  619.           WriteCH('-')
  620.         ELSE 
  621.           WriteCH(' ')  
  622.         END;
  623.         La:=La+Latoi(Tenth,sigdigits,dummy)*Five;
  624.         IF TRUNCd(La)>LONG(9) THEN
  625.           La:=La*Tenth;
  626.           INC(i)
  627.         END;
  628.         FOR l:=1 TO sigdigits DO
  629.           k:=TRUNCd(La);
  630.           IF k>9 THEN 
  631.             k:=9;
  632.             La:=Ten
  633.           END;
  634.           WriteCH(CHR(k+ORD('0')));
  635.           La:=Ten*(La-FLOATd(k));
  636.           IF La<Zero THEN La:=Zero END;
  637.           IF l=placesbeforedot THEN WriteCH('.') END
  638.         END;
  639.         IF (i<>0) OR LongForceExponent THEN
  640.           WriteCH('E');
  641.           IF i<0 THEN
  642.             WriteCH('-');
  643.             i:=-i
  644.           ELSE 
  645.             WriteCH('+');
  646.           END;
  647.           FOR k:=1 TO 3 DO
  648.             j:=i DIV 10;
  649.             l:=i-10*j;
  650.             chs[k]:=CHR(l+ORD('0'));
  651.             i:=j
  652.           END;
  653.           FOR k:=3 TO 1 BY -1 DO  WriteCH(chs[k]) END
  654.         END;
  655.         Text[pos]:=0C
  656.       END LongRealToString;
  657.      
  658.     PROCEDURE WriteLongReal(c : LONGREAL; size : INTEGER);
  659.       VAR s : String;
  660.       BEGIN
  661.         LongRealToString(s,c,size);
  662.         WriteString(s)
  663.       END WriteLongReal;
  664.  
  665.     PROCEDURE LongRealToStringFixed
  666.           (VAR Text : ARRAY OF CHAR; x : LONGREAL; size, places : INTEGER);
  667.       (*  output a longreal number *)
  668.       VAR  placesbeforedot  : INTEGER;
  669.            wholeplaces      : INTEGER;
  670.            pos, k, l        : INTEGER;
  671.            digitnumber      : INTEGER;
  672.            storeSigDigits   : INTEGER;
  673.            storeEngineering : BOOLEAN;
  674.            dummy            : BOOLEAN;
  675.       PROCEDURE WriteCH(ch : CHAR);
  676.         BEGIN
  677.           IF pos<HIGH(Text) THEN
  678.             Text[pos]:=ch;
  679.             INC(pos)
  680.           END
  681.         END WriteCH;
  682.       BEGIN
  683.         IF size>=HIGH(Text) THEN size:=HIGH(Text)-1 END;
  684.         pos:=0;
  685.         La:=x;
  686.         LPreScale;
  687.         IF places>15 THEN places:=15 END;
  688.         IF size=0 THEN size:=1 END;
  689.         IF (size=1) & neg THEN size:=2 END;
  690.         IF places>size-1 THEN places:=size-1 END;
  691.         placesbeforedot:=size-places-1;
  692.         IF neg & (placesbeforedot>0)THEN DEC(placesbeforedot) END;
  693.         IF i<=0 THEN    
  694.           wholeplaces:=1;
  695.           La:=ABS(x);
  696.           i:=0
  697.         ELSE            
  698.           wholeplaces:=i+1 
  699.         END;
  700.         IF wholeplaces>placesbeforedot THEN 
  701.           storeSigDigits:=LongSigDigits;
  702.           storeEngineering:=LongEngineering;
  703.           LongSigDigits:=places+1;
  704.           LongEngineering:=FALSE;
  705.           LongRealToString(Text,x,size);
  706.           LongSigDigits:=storeSigDigits;
  707.           LongEngineering:=storeEngineering;
  708.           RETURN
  709.         END;
  710.         La:=La+Latoi(Tenth,wholeplaces+places,dummy)*Five;
  711.         FOR l:=placesbeforedot TO wholeplaces+1 BY -1 DO WriteCH(' ') END;
  712.         IF neg THEN WriteCH('-') END;
  713.         digitnumber:=1;
  714.         FOR l:=wholeplaces TO 1 BY -1 DO
  715.           k:=TRUNCd(La);
  716.           IF k>9 THEN k:=9 END;
  717.           IF digitnumber<=LMaxDigits THEN
  718.             WriteCH(CHR(k+nul))
  719.           ELSE
  720.             WriteCH('0')
  721.           END;
  722.           INC(digitnumber);
  723.           La:=Ten*(La-FLOATd(k));
  724.           IF La<Zero THEN La:=Zero END
  725.         END;
  726.         IF digitnumber<=LMaxDigits THEN WriteCH('.') ELSE WriteCH(' ') END;
  727.         FOR l:=1 TO places DO
  728.           k:=TRUNCd(La);
  729.           IF k>9 THEN k:=9; La:=Ten END;
  730.           IF digitnumber<=LMaxDigits THEN
  731.             WriteCH(CHR(k+ORD('0')))
  732.           ELSE 
  733.             WriteCH(' ')
  734.           END;
  735.           INC(digitnumber);
  736.           La:=Ten*(La-FLOATd(k));
  737.           IF La<Zero THEN La:=Zero END
  738.         END;
  739.         Text[pos]:=0C
  740.       END LongRealToStringFixed;
  741.     
  742.     PROCEDURE WriteLongRealFixed(x : LONGREAL; size, places : INTEGER);
  743.       VAR s : String;
  744.       BEGIN
  745.         LongRealToStringFixed(s,x,size,places);
  746.         WriteString(s)
  747.       END WriteLongRealFixed;
  748.   
  749.   PROCEDURE WriteHexDig(C : INTEGER);
  750.     BEGIN 
  751.       IF C>9 THEN INC(C,ORD('A')-ORD('9')-1) END;
  752.       Write(CHR(C+nul))
  753.     END WriteHexDig;
  754.     
  755.   PROCEDURE WriteOctGroup(C : CHAR);
  756.     VAR p, q : CARDINAL;
  757.     BEGIN
  758.       p:=ORD(C);
  759.       q:=p DIV 100B;
  760.       WriteHexDig(q);
  761.       p:=p-100B*q;
  762.       q:=p DIV 10B;
  763.       WriteHexDig(q);
  764.       q:=p-10B*q;
  765.       WriteHexDig(q)
  766.     END WriteOctGroup;
  767.     
  768.   TYPE PLC = RECORD
  769.                CASE : BOOLEAN OF
  770.                  TRUE : P : POINTER TO CHAR |
  771.                  FALSE: C : LONGCARD
  772.                END
  773.              END;
  774.  
  775.   PROCEDURE WriteRealOct(x : REAL; n : CARDINAL);
  776.     VAR a : PLC;
  777.         k : CARDINAL;
  778.     BEGIN
  779.       a.P:=ADR(x);
  780.       FOR k:=1 TO 4 DO
  781.         WriteOctGroup(a.P^);
  782.         IF n>=16 THEN Write(' ') END;
  783.         INC(a.C)
  784.       END
  785.     END WriteRealOct;
  786.     
  787.   PROCEDURE WriteLongRealOct(x : LONGREAL; n : CARDINAL);
  788.     VAR a : PLC;
  789.         k : CARDINAL;
  790.     BEGIN
  791.       a.P:=ADR(x);
  792.       FOR k:=1 TO 8 DO
  793.         WriteOctGroup(a.P^);
  794.         IF n>=32 THEN Write(' ') END;
  795.         INC(a.C)
  796.       END
  797.     END WriteLongRealOct;
  798.     
  799.   PROCEDURE WriteHexGroup(C : CHAR);
  800.     VAR p, q : CARDINAL;
  801.     BEGIN
  802.       p:=ORD(C);
  803.       q:=p DIV 10H;
  804.       WriteHexDig(q);
  805.       q:=p-10H*q;
  806.       WriteHexDig(q)
  807.     END WriteHexGroup;
  808.   
  809.   PROCEDURE WriteRealHex(x : REAL; n : CARDINAL);
  810.     VAR a : PLC;
  811.         k : CARDINAL;
  812.     BEGIN
  813.       a.P:=ADR(x);
  814.       FOR k:=1 TO 4 DO
  815.         WriteHexGroup(a.P^);
  816.         IF n>=12 THEN Write(' ') END;
  817.         INC(a.C)
  818.       END
  819.     END WriteRealHex;
  820.     
  821.   PROCEDURE WriteLongRealHex(x : LONGREAL; n : CARDINAL);
  822.     VAR a : PLC;
  823.         k : CARDINAL;
  824.     BEGIN
  825.       a.P:=ADR(x);
  826.       FOR k:=1 TO 8 DO
  827.         WriteHexGroup(a.P^);
  828.         IF n>=24 THEN Write(' ') END;
  829.         INC(a.C)
  830.       END
  831.     END WriteLongRealHex;
  832.     
  833. BEGIN
  834.   
  835.     Engineering:=FALSE;
  836.     SigDigits:=MaxDigits;
  837.     ForceExponent:=TRUE;
  838.     MINREAL:=1.0/MAX(REAL);
  839.  
  840.     LongEngineering:=FALSE;
  841.     LongSigDigits:=LMaxDigits;
  842.     LongForceExponent:=TRUE;
  843.    
  844.     nul:=ORD('0');
  845.     
  846.     Zero:=0.0;
  847.     One :=1.0;
  848.     Five:=5.0;
  849.     Ten :=10.0;
  850.     TwoEM16:=2.0E-16;
  851.     Tenth:=Rec(Ten);
  852.     E14:=1.0E14;
  853.     EM14:=Rec(E14);
  854.     EM4 :=Rec(1.0E4);
  855.     EM8 :=Rec(1.0E8);
  856.     EM12:=Rec(1.0E12);
  857.     EM16:=Rec(1.0E16);
  858.     EM20:=Rec(1.0E20);
  859.     MinLong:=One/MAX(LONGREAL);
  860.  
  861.      
  862.    
  863. END RealInOut.
  864.